package ex1;

/**
 * SynchedCell extends NormalCell.
 * A synchronized cell represents a cell which resides on the borders of the threads (aka workers).
 * The SynchedCell class overrides the relevant functions of NormalCell to allow synchornization.
 */
public class SynchedCell extends NormalCell {
	
	Thread owner;
	
	/**
	 * Constructor of SynchedCell.
	 * 
	 * @param state the initial state of the cell.
	 * @param maxGen the desired maximal generation.
	 * @param owner the owning thread (worker) of the cell. This is used in order to wake waiting (unoccopied) workers.
	 */
	public SynchedCell (boolean state, int maxGen, Thread owner) {
		super(state, maxGen);
		this.owner = owner;
	}
	
	/**
	 * Synchornized version of getState. 
	 * Accquires self-cell's lock before getting state.
	 * 
	 * @see NormalCell#getState(int)
	 */
	public boolean getState (int generation) throws NotReady {
		synchronized(this) { return super.getState(generation); }
	}
	
	/**
	 * Synchornized version of nextState. 
	 * Accquires self-cell's lock before setting state.
	 * 
	 * @see NormalCell#nextState(boolean)
	 */
	protected void nextState (boolean state) {
		synchronized(this) { super.nextState(state); }
	}
	
	/**
	 * Synchornized version of evolve. 
	 * Calls NormalCell's evolve(), and if an evolution occured - wakes up owners of all the neighbours.
	 * 
	 * @see NormalCell#evolve()
	 */
	public boolean evolve () {
		boolean evolved = super.evolve();
		if (evolved)
			for (ICell n : neighbours)
				n.wakeOwner();
		return evolved;
	}

	/**
	 * Accquires lock of the owning thread, and awakens it by calling notifyAll().
	 * 
	 * @see ICell#wakeOwner()
	 */
	public void wakeOwner () {
		synchronized(owner) { owner.notifyAll(); }
	}
	
}
